package cn.fintecher.pangolin.service.manage.service;

import cn.fintecher.pangolin.common.annotation.ExcelAnno;
import cn.fintecher.pangolin.common.enums.BaseSelect;
import cn.fintecher.pangolin.common.enums.ConfigState;
import cn.fintecher.pangolin.common.exception.BadRequestException;
import cn.fintecher.pangolin.common.model.CaseFollowRecordMatchModel;
import cn.fintecher.pangolin.common.model.UserModel;
import cn.fintecher.pangolin.common.utils.BeanUtils;
import cn.fintecher.pangolin.entity.mysql.ContactConfig;
import cn.fintecher.pangolin.entity.mysql.QContactConfig;
import cn.fintecher.pangolin.entity.mysql.User;
import cn.fintecher.pangolin.service.manage.model.FollowRecordFieldModel;
import cn.fintecher.pangolin.service.manage.repository.ContactConfigRepository;
import cn.fintecher.pangolin.service.manage.request.AddContactConfigRequest;
import cn.fintecher.pangolin.service.manage.response.ContactConfigResponse;
import cn.fintecher.pangolin.service.manage.response.ContactConfigTreeResponse;
import cn.fintecher.pangolin.service.manage.response.PrincipalResponse;
import com.google.common.collect.Lists;
import com.querydsl.core.BooleanBuilder;
import org.apache.commons.collections4.IterableUtils;
import org.modelmapper.ModelMapper;
import org.modelmapper.TypeToken;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Auther: xiaqun
 * @Description:
 * @Date: 10:58 2019/9/12
 */

@Service("contactConfigService")
@Transactional(rollbackFor = Exception.class)
public class ContactConfigService {
    @Autowired
    private ContactConfigRepository contactConfigRepository;

    @Autowired
    private ModelMapper modelMapper;

    @Autowired
    private BaseService baseService;

    /**
     * 查询联络配置树结构addPrincipal
     */
    public List<ContactConfigTreeResponse> getContactConfigTree(String token) {
        UserModel userModel = baseService.getUserByToken(token);
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        if (userModel.getIsCheck().equals(BaseSelect.YES)) {
            booleanBuilder.and(QContactConfig.contactConfig.principalId.in(userModel.getPrincipalIds()));
        }
        booleanBuilder.and(QContactConfig.contactConfig.isInitData.eq(BaseSelect.NO));
        Iterable<ContactConfig> iterable = contactConfigRepository.findAll(booleanBuilder);
        Type listType = new TypeToken<List<ContactConfigTreeResponse>>() {
        }.getType();
        return modelMapper.map(IterableUtils.toList(iterable), listType);
    }

    /**
     * 获取子集
     */
    public List<ContactConfig> getChildren(String id) {
        return IterableUtils.toList(contactConfigRepository.findAll(QContactConfig.contactConfig.parent.eq(id)));
    }

    /**
     * 根据ID获取配置信息
     */
    public ContactConfigResponse getContactConfigById(String id) {
        ContactConfig config = contactConfigRepository.findById(id).orElseThrow(() -> new BadRequestException(null, "contactConfig", "contactConfig.is.null"));
        ContactConfigResponse contactConfigResponse = new ContactConfigResponse();
        BeanUtils.copyPropertiesIgnoreNull(config, contactConfigResponse);
        if (!config.getHideList().isEmpty()) {
            contactConfigResponse.setHideList(config.getHideList().stream().map(ContactConfig::getId).collect(Collectors.toList()));
        }
        return contactConfigResponse;
    }

    /**
     * 新增联络配置
     */
    public void addContactConfig(AddContactConfigRequest request) {
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        booleanBuilder.and(QContactConfig.contactConfig.name.eq(request.getName())).and(QContactConfig.contactConfig.principalId.eq(request.getPrincipalId()));
        boolean exists = contactConfigRepository.exists(booleanBuilder);
        if (exists) {
            throw new BadRequestException(null, "addContactConfig", "config.name.is.exists");
        }
        if (Objects.equals(request.getLevel(), 2)) {
            BooleanBuilder builder = new BooleanBuilder();
            builder.and(QContactConfig.contactConfig.attribute.eq(request.getAttribute())).and(QContactConfig.contactConfig.principalId.eq(request.getPrincipalId()))
                    .and(QContactConfig.contactConfig.isInitData.eq(BaseSelect.NO));
            boolean isExists = contactConfigRepository.exists(builder);
            if (isExists) {
                throw new BadRequestException(null, "addContactConfig", "config.attribute.is.exists");
            }
        }
        ContactConfig contactConfig = new ContactConfig();
        if (!request.getHideList().isEmpty()) {
            List<ContactConfig> configList = contactConfigRepository.findAllById(request.getHideList());
            for (ContactConfig contactConfigHidden : configList) {
                contactConfigHidden.setConfigState(ConfigState.DISABLED);
            }
            contactConfig.setHideList(new HashSet<>(configList));
        }
        BeanUtils.copyPropertiesIgnoreNull(request, contactConfig);
        contactConfig.setId(UUID.randomUUID().toString().replaceAll("-", ""));
        contactConfigRepository.save(contactConfig);
    }

    /**
     * 修改联络配置
     */
    public void modifyContactConfig(AddContactConfigRequest request) {
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        booleanBuilder.and(QContactConfig.contactConfig.name.eq(request.getName()))
                .and(QContactConfig.contactConfig.principalId.eq(request.getPrincipalId()))
                .and(QContactConfig.contactConfig.id.ne(request.getId()));
        boolean exists = contactConfigRepository.exists(booleanBuilder);
        if (exists) {
            throw new BadRequestException(null, "modifyContactConfig", "config.name.is.exists");
        }
        if (Objects.equals(request.getLevel(), 2)) {
            BooleanBuilder builder = new BooleanBuilder();
            builder.and(QContactConfig.contactConfig.attribute.eq(request.getAttribute())).and(QContactConfig.contactConfig.principalId.eq(request.getPrincipalId()))
                    .and(QContactConfig.contactConfig.id.ne(request.getId()));
            boolean isExists = contactConfigRepository.exists(builder);
            if (isExists) {
                throw new BadRequestException(null, "modifyContactConfig", "config.attribute.is.exists");
            }
        }
        ContactConfig contactConfig = contactConfigRepository.findById(request.getId()).orElseThrow(() -> new BadRequestException(null, "contactConfig", "contactConfig.is.null"));
        Set<ContactConfig> historyList = contactConfig.getHideList();
        for (ContactConfig historyConfig : historyList) {
            historyConfig.setConfigState(ConfigState.ENABLED);
        }
        contactConfig.setName(request.getName());
        contactConfig.setSort(request.getSort());
        contactConfig.setIsExtension(request.getIsExtension());
        contactConfig.setIsRecord(request.getIsRecord());
        contactConfig.setIsNecessary(request.getIsNecessary());
        contactConfig.setLimitNumber(request.getLimit());
        contactConfig.setAttribute(request.getAttribute());
        contactConfig.setPrincipalId(request.getPrincipalId());
        contactConfig.setPrincipalName(request.getPrincipalName());
        if (Objects.nonNull(request.getHideList()) && !request.getHideList().isEmpty()) {
            List<ContactConfig> configList = contactConfigRepository.findAllById(request.getHideList());
            for (ContactConfig contactConfigHidden : configList) {
                contactConfigHidden.setConfigState(ConfigState.DISABLED);
            }
            contactConfig.setHideList(new HashSet<>(configList));
        } else {
            contactConfig.setHideList(null);
        }
        contactConfigRepository.save(contactConfig);
    }

    /**
     * 删除联络配置
     */
    public void deleteContactConfig(String id) {
        List<ContactConfig> contactConfigList = new ArrayList<>();
        findAllByParentId(contactConfigList, id);
        if (contactConfigList.size() > 0) {
            contactConfigRepository.deleteAll(contactConfigList);
        }
        contactConfigRepository.deleteById(id);
    }

    /**
     * @Author wangxiangdong
     * @Description 递归查找所有配置
     * @Date 2019/11/11 10:06
     **/
    private void findAllByParentId(List<ContactConfig> contactConfigList, String id) {
        List<ContactConfig> contactConfigSubList = Lists.newArrayList(contactConfigRepository.findAll(QContactConfig.contactConfig.parent.eq(id)));
        if (contactConfigSubList.size() > 0) {
            contactConfigList.addAll(contactConfigSubList);
            for (ContactConfig contactConfig : contactConfigSubList) {
                findAllByParentId(contactConfigList, contactConfig.getId());
            }
        }

    }


    /**
     * 查询没有联络配的委托方
     */
    public List<PrincipalResponse> getPrincipalNoConfig(String token) {
        UserModel userModel = baseService.getUserByToken(token);
        List<PrincipalResponse> responses = new ArrayList<>();
        List<Object[]> list = contactConfigRepository.getPrincipalNoConfig();
        if (userModel.getIsCheck().equals(BaseSelect.YES)) {
            for (Object[] obj : list) {
                if(userModel.getPrincipalIds().contains(obj[0].toString())) {
                    PrincipalResponse response = new PrincipalResponse();
                    response.setId(obj[0].toString());
                    response.setName(obj[1].toString());
                    responses.add(response);
                }
            }
        } else {
            for (Object[] obj : list) {
                PrincipalResponse response = new PrincipalResponse();
                response.setId(obj[0].toString());
                response.setName(obj[1].toString());
                responses.add(response);
            }
        }
        return responses;
    }

    /**
     * 查询跟进记录字段项
     */
    public List<CaseFollowRecordMatchModel> getFollowMarchRecord() {
        List<CaseFollowRecordMatchModel> matchModels = new ArrayList<>();
        Field[] fields = FollowRecordFieldModel.class.getDeclaredFields();
        for (Field field : fields) {
            if (field.isAnnotationPresent(ExcelAnno.class)) {
                ExcelAnno f = field.getAnnotation(ExcelAnno.class);
                CaseFollowRecordMatchModel matchModel = new CaseFollowRecordMatchModel();
                matchModel.setAttribute(field.getName());
                matchModel.setName(f.cellName());
                matchModel.setPropertyType(f.fieldType().name());
                matchModel.setIsMustInput(f.fieldInput().name());
                if (!f.fieldDataType().equals(ExcelAnno.FieldDataType.NULL)) {
                    matchModel.setFieldDataType(f.fieldDataType().name());
                }
                matchModels.add(matchModel);
            }
        }
        return matchModels;
    }

    /**
     * 查询跟进记录映射字段
     */
    public List<ContactConfig> getAllContactConfig(String principalId) {
        BooleanBuilder builder = new BooleanBuilder();
        builder.and(QContactConfig.contactConfig.principalId.eq(principalId).and(QContactConfig.contactConfig.level.eq(2)));
        Iterable<ContactConfig> iterable = contactConfigRepository.findAll(builder);
        return IterableUtils.toList(iterable);
    }

    /**
     * 查询催记匹配字段
     */
    public List<ContactConfigResponse> getFollowRecordFields(String principalId) {
        QContactConfig qContactConfig = QContactConfig.contactConfig;
        Iterable<ContactConfig> iterable = contactConfigRepository.findAll(qContactConfig.principalId.eq(principalId).and(qContactConfig.level.eq(2))
                .and(qContactConfig.isInitData.eq(BaseSelect.NO)).and(QContactConfig.contactConfig.attribute.notIn("addrType", "addrStatus")));
        Type listType = new TypeToken<List<ContactConfigResponse>>() {
        }.getType();
        List<ContactConfigResponse> responses = modelMapper.map(IterableUtils.toList(iterable), listType);
        responses.forEach(e -> {
            if (Objects.equals(e.getPropertyType(), ExcelAnno.FieldType.SELECT.name()) || Objects.equals(e.getPropertyType(), ExcelAnno.FieldType.CASCADER.name())) {
                Iterable<ContactConfig> iterable1 = contactConfigRepository.findAll(qContactConfig.parent.eq(e.getId()).and(qContactConfig.level.eq(3)));
                e.setChildList(IterableUtils.toList(iterable1));
            }
        });
        return responses;
    }

    /**
     * 查询联系人关系/电话类型/地址类型
     */
    public Set<String> getReflect(String principalId, String attribute) {
        Set<String> set = new HashSet<>();
        Optional<ContactConfig> optional = contactConfigRepository.findOne(QContactConfig.contactConfig.principalId.eq(principalId)
                .and(QContactConfig.contactConfig.attribute.eq(attribute)));
        if (optional.isPresent()) {
            ContactConfig contactConfig = optional.get();
            Iterable<ContactConfig> iterable = contactConfigRepository.findAll(QContactConfig.contactConfig.parent.eq(contactConfig.getId()));
            iterable.forEach(e -> set.add(e.getName()));
        }
        return set;
    }
}
